package com.kust.smarthome.web.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kust.smarthome.web.dto.UserDto;
import com.kust.smarthome.web.mapper.*;
import com.kust.smarthome.web.model.*;
import com.kust.smarthome.web.service.IUserService;
import com.kust.smarthome.web.utils.EmailUtils;
import com.kust.smarthome.web.vo.RegisterVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.mail.MessagingException;
import java.security.GeneralSecurityException;
import java.time.LocalDateTime;
import java.util.UUID;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private UserMapper userMapper;

    @Resource
    private EmailCodeMapper emailCodeMapper;

    @Autowired(required = false)
    private EmailUtils emailUtils;

    @Autowired
    private LampMapper lampMapper;

    @Autowired
    private AirConditionerMapper airConditionerMapper;

    @Autowired
    private CurtainMapper curtainMapper;

    @Autowired
    private DetectorMapper detectorMapper;

    @Autowired
    private DoorMapper doorMapper;

    @Autowired
    private HygrothermographMapper hygrothermographMapper;

    @Autowired
    private TelevisionMapper televisionMapper;

    @Autowired
    private DeviceStateMapper deviceStateMapper;

    @Autowired
    private RoomMapper roomMapper;

    @Override
    public User getByUsername(String username) {
        QueryWrapper<User> query = new QueryWrapper<>();
        query.eq("username",username);
        return userMapper.selectOne(query);
    }

    /**
     * 注册功能,以email为username,username为nickname,
     * @param registerVo 注册信息
     * @return 返回注册成功与否信息
     */
    @Override
    @Transactional
    public String register(RegisterVo registerVo) {

        if (!registerVo.getPassword1().equals(registerVo.getPassword2()))
            return "密码不一致!";

        QueryWrapper<User> query = new QueryWrapper<>();
        query.eq("username",registerVo.getEmail());
        User u = userMapper.selectOne(query);

        if (u != null)
            return "邮箱已被注册";

        QueryWrapper<EmailCode> eQuery = new QueryWrapper<>();
        eQuery.eq("email", registerVo.getEmail());
        EmailCode emailCode = emailCodeMapper.selectOne(eQuery);
        if (emailCode == null)
            return "与验证邮箱不同,注册失败!";
        if (emailCode.getState() != 1)
            return "验证失败!";

        PasswordEncoder encoder = new BCryptPasswordEncoder();

        User user = new User()
                .setNickname(registerVo.getNickname())
                .setUsername(registerVo.getEmail())
                .setPortrait("http://xiangrikui.resource.vaiwan.com/portrait.png") //默认头像
                .setPassword(encoder.encode(registerVo.getPassword1()))
                .setEnabled(1)
                .setLocked(0)
                .setCreated(LocalDateTime.now())
                .setState(1)
                .setPower(0);

        emailCodeMapper.deleteById(emailCode.getId());

        int num = userMapper.insert(user);
        if (num == 1) {
            registerUtil(user);
            return "注册成功";
        }

        return "注册失败";
    }

    @Transactional
    public void registerUtil(User user) {

        Room room = new Room()
                .setUserId(user.getId())
                .setName(user.getNickname() + "的小屋")
                .setTypeId(1);
        roomMapper.insert(room);

        //灯1
        QueryWrapper<Lamp> queryLamp = new QueryWrapper<>();
        queryLamp.orderByDesc("id").last("limit 1");
        Lamp l = lampMapper.selectOne(queryLamp);
        Lamp lamp1 = new Lamp()
                .setId(l.getId()+1)
                .setUrl("")
                .setName("室内灯")
                .setContent("noshow")
                .setState(0)
                .setCreated(LocalDateTime.now())
                .setRoomId(room.getId())
                .setUserId(user.getId());
        lampMapper.insert(lamp1);

        DeviceState deviceState1 = new DeviceState()
                .setDeviceId(lamp1.getId())
                .setTypeId(1)
                .setIsUpdate(0);
        //插入状态变更通知
        deviceStateMapper.insert(deviceState1);

        //灯2
        Lamp lamp2 = new Lamp()
                .setId(l.getId()+2)
                .setUrl("")
                .setName("室外灯")
                .setContent("noshow")
                .setState(0)
                .setCreated(LocalDateTime.now())
                .setRoomId(room.getId())
                .setUserId(user.getId());
        lampMapper.insert(lamp2);

        DeviceState deviceState2 = new DeviceState()
                .setDeviceId(lamp2.getId())
                .setTypeId(1)
                .setIsUpdate(0);
        //插入状态变更通知
        deviceStateMapper.insert(deviceState2);

        //空调
        QueryWrapper<AirConditioner> queryAir = new QueryWrapper<>();
        queryAir.orderByDesc("id").last("limit 1");
        AirConditioner a = airConditionerMapper.selectOne(queryAir);
        AirConditioner airConditioner = new AirConditioner()
                .setId(a.getId() + 1)
                .setUrl("")
                .setContent("21;noopen")
                .setState(0)
                .setCreated(LocalDateTime.now())
                .setUserId(user.getId())
                .setRoomId(room.getId());
        airConditionerMapper.insert(airConditioner);

        DeviceState deviceStateAir = new DeviceState()
                .setDeviceId(a.getId() + 1)
                .setTypeId(6)
                .setIsUpdate(0);
        //插入状态变更通知
        deviceStateMapper.insert(deviceStateAir);

        //窗帘
        QueryWrapper<Curtain> queryC = new QueryWrapper<>();
        queryC.orderByDesc("id").last("limit 1");
        Curtain c = curtainMapper.selectOne(queryC);
        Curtain curtain = new Curtain()
                .setId(c.getId() + 1)
                .setUrl("")
                .setName("窗帘")
                .setContent("isopen")
                .setState(0)
                .setCreated(LocalDateTime.now())
                .setUserId(user.getId())
                .setRoomId(room.getId());
        curtainMapper.insert(curtain);
        DeviceState deviceStateC = new DeviceState()
                .setDeviceId(c.getId())
                .setTypeId(2)
                .setIsUpdate(0);
        deviceStateMapper.insert(deviceStateC);

        //烟雾报警器
        QueryWrapper<Detector> queryD = new QueryWrapper<>();
        queryD.orderByDesc("id").last("limit 1");
        Detector d = detectorMapper.selectOne(queryD);
        Detector detector = new Detector()
                .setUrl("")
                .setId(d.getId() + 1)
                .setName("烟雾报警器")
                .setContent("300")
                .setState(0)
                .setCreated(LocalDateTime.now())
                .setUserId(user.getId())
                .setRoomId(room.getId());
        detectorMapper.insert(detector);
        DeviceState deviceStateD = new DeviceState()
                .setDeviceId(d.getId() + 1)
                .setTypeId(4)
                .setIsUpdate(0);
        //插入状态变更通知
        deviceStateMapper.insert(deviceStateD);

        QueryWrapper<Door> queryDoor = new QueryWrapper<>();
        queryDoor.orderByDesc("id").last("limit 1");
        Door door0 = doorMapper.selectOne(queryDoor);
        Door door = new Door()
                .setId(door0.getId() + 1)
                .setUrl("")
                .setName("大门")
                .setContent("noopen")
                .setState(0)
                .setCreated(LocalDateTime.now())
                .setUserId(user.getId())
                .setPassword("123456")
                .setRoomId(room.getId());
        doorMapper.insert(door);
        DeviceState deviceStateDoor = new DeviceState()
                .setDeviceId(door0.getId() + 1)
                .setTypeId(3)
                .setIsUpdate(0);
        deviceStateMapper.insert(deviceStateDoor);

        //温湿度计
        QueryWrapper<Hygrothermograph> queryH = new QueryWrapper<>();
        queryH.orderByDesc("id").last("limit 1");
        Hygrothermograph h = hygrothermographMapper.selectOne(queryH);
        Hygrothermograph hygrothermograph = new Hygrothermograph()
                .setId(h.getId() + 1)
                .setUrl("")
                .setName("温湿度计")
                .setContent("C:0;H:0")
                .setState(1)
                .setCreated(LocalDateTime.now())
                .setUserId(user.getId())
                .setRoomId(room.getId());
        hygrothermographMapper.insert(hygrothermograph);
        DeviceState deviceStateH = new DeviceState()
                .setDeviceId(h.getId() + 1)
                .setTypeId(7)
                .setIsUpdate(0);
        deviceStateMapper.insert(deviceStateH);

        //电视
        QueryWrapper<Television> queryT = new QueryWrapper<>();
        queryT.orderByDesc("id").last("limit 1");
        Television t = televisionMapper.selectOne(queryT);
        Television television = new Television()
                .setId(t.getId() + 1)
                .setUrl("")
                .setName("客厅电视")
                .setContent("isopen")
                .setState(0)
                .setCreated(LocalDateTime.now())
                .setUserId(user.getId())
                .setRoomId(room.getId());
        televisionMapper.insert(television);
        DeviceState deviceStateT = new DeviceState()
                .setDeviceId(t.getId()+1)
                .setTypeId(5)
                .setIsUpdate(0);
        deviceStateMapper.insert(deviceStateT);



    }

    @Override
    public UserDto getUserInfo(Integer userId) {

        return userMapper.getUserInfo(userId);
    }

    @Override
    public User findByUsername(String username) {

        return userMapper.findByUsername(username);
    }

    @Override
    @Transactional
    public String appRegister(RegisterVo registerVo) throws GeneralSecurityException, MessagingException {

        if (!registerVo.getPassword1().equals(registerVo.getPassword2()))
            return "密码不一致!";

        User user = userMapper.findByUsername(registerVo.getEmail());
        if (user != null)
            return "该邮箱已被注册!";

        PasswordEncoder encoder = new BCryptPasswordEncoder();

        user = new User()
                .setNickname(registerVo.getNickname())
                .setUsername(registerVo.getEmail())
                .setPortrait("http://xiangrikui.resource.vaiwan.com/portrait.png") //默认头像
                .setPassword(encoder.encode(registerVo.getPassword1()))
                .setEnabled(1)
                .setLocked(1)
                .setCreated(LocalDateTime.now())
                .setState(1)
                .setPower(0);
        String code = UUID.randomUUID().toString().replace("-","");
        EmailCode emailCode = new EmailCode()
                .setEmail(registerVo.getEmail())
                .setCode(code)
                .setState(0);
        emailCodeMapper.insert(emailCode);

        String url = "请点击下面连接对您的账户进行激活:" + "http://xiangrikui.vaiwan.com/appCode?" +
                "id=" + emailCode.getId() +
                "&code=" + code;
        emailUtils.sendEmail(registerVo.getEmail(), "新用户激活", url);

        userMapper.insert(user);
        registerUtil(user);

        return "注册成功,请前往邮箱激活账号!";
    }

    @Override
    public String appCode(EmailCode emailCode) {

        User user = getByUsername(emailCode.getEmail());
        user.setLocked(0);
        userMapper.updateById(user);

        emailCodeMapper.deleteById(emailCode.getId());

        return "注册成功!";

    }


}
